home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Libraries / objects in c ƒ / OIC Sources / oic.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-07  |  18.8 KB  |  842 lines  |  [TEXT/KAHL]

  1. /*
  2.  *        Objects-in-C object manager
  3.  *
  4.  *            Copyright © John Wainwright 1988
  5.  *
  6.  */
  7.  
  8. #include <stdio.h>
  9. #include "oic.h"
  10. #include "generics.h"
  11. #include "varargs.h"
  12.  
  13. #define CHECK_OBJS    1                /* turn on or off object checking         */
  14. /* #define IGNORE_NULL_OBJS 1         /* ignore generics on NULL objects        */
  15.  
  16. class              currentClass;        /* class of currently exec'ing method    */
  17. int                currentClassIndex;    /* index of current class                */
  18. GenericTable    *currentGeneric;    /* current generic method table            */
  19. GenericTable    *generics;            /* linked list of generic tables        */
  20.  
  21. static int        trace;                 /* trace flag                             */
  22. static class      trace_class;        /* class for class constrained trace     */
  23. static object    trace_obj;             /* obj for obj constrained trace         */
  24. static int        gen_level;            /* generic nest level                     */
  25. static int        class_index;        /* class index generator                */
  26.  
  27. /*---------------------------- Class Maker  -----------------------------    */
  28.  
  29. /*    
  30.  *     create a new class.
  31.  */
  32. class  
  33. NewClass(ivsize, cvsize, name, va_alist)
  34.     int        ivsize, cvsize;
  35.     char    *name;
  36.     va_dcl
  37. {
  38.     va_list             pvar;
  39.     register class       c;
  40.     register class       superclass;
  41.     register classlist  **clp;
  42.     register int        cvallocz;
  43.     register int        nsupers;
  44.     int                    ivoffset, cvoffset;
  45.     char                *strcpy(), *salloc();
  46.  
  47.     c = talloc(struct class_struct);
  48.     c->c_classtag = Class;
  49.     c->c_index = ++class_index; /* origin 1        */
  50.     c->c_name = strcpy(salloc(strlen(name) + 1), name);
  51.     c->c_lclivsize = (ivsize + sizeof(char *) - 1) & ~(sizeof(char *) - 1);
  52.     c->c_lclcvsize = (cvsize + sizeof(char *) - 1) & ~(sizeof(char *) - 1);
  53.     c->c_next = classes;
  54.     classes = c;
  55.     
  56.     /* build the supers list */
  57.     
  58.     c->c_ivsize = c->c_cvsize = 0;
  59.     clp = &c->c_superclasses;
  60.     va_start(pvar);
  61.     for (nsupers = 0;  (superclass = va_arg(pvar, class)) != END; )
  62.     {
  63.         if (superclass->c_classtag != Class)
  64.             gprintf(error, "NewClass (%s): super %d is not a class\n", name, nsupers+1);            
  65.         *clp = talloc(classlist);
  66.         (*clp)->cl_class = superclass;
  67.         clp = &(*clp)->cl_next;
  68.         
  69.         c->c_ivsize += superclass->c_ivsize;
  70.         c->c_cvsize += superclass->c_cvsize;
  71.         c->c_flags |= (superclass->c_flags & C_HASCLASSMETHODS);
  72.         nsupers += 1;
  73.     }
  74.     
  75.     if (nsupers == 0)        /* inherit, at least, from Object        */
  76.     {
  77.         *clp = talloc(classlist);
  78.         (*clp)->cl_class = Object;
  79.         clp = &(*clp)->cl_next;
  80.     }
  81.     
  82.     *clp = END;
  83.     
  84.     /* construct the IV & CV offset tables */
  85.     
  86.     c->c_ivoffsets = (int *)scalloc(sizeof(int) * (c->c_index + 1));
  87.     c->c_ivoffsets[c->c_index] = c->c_ivsize + sizeof(object);
  88.     
  89.     if ((c->c_flags & C_HASCLASSMETHODS) |        /* CV offsets only if used    */
  90.         (c->c_cvsize + c->c_lclcvsize) != 0)
  91.     {
  92.         c->c_cvoffsets = (int *)scalloc(sizeof(int) * (c->c_index + 1));
  93.         c->c_cvoffsets[c->c_index] = c->c_cvsize + sizeof(object);
  94.     }
  95.     
  96.     ivoffset = cvoffset = sizeof(object);
  97.     buildOffsetTables(c, c->c_superclasses, &ivoffset, &cvoffset);
  98.     
  99.     /* compute complete object's allocation size */
  100.     
  101.     c->c_ivsize += c->c_lclivsize;
  102.     c->c_allocz = c->c_ivsize + sizeof(object);
  103.     
  104.     /*  allocate any class variable structure for this class    */
  105.  
  106.     c->c_cvsize += c->c_lclcvsize;
  107.     if (c->c_cvsize)
  108.         c->c_classvars = scalloc(c->c_cvsize + sizeof(object));
  109.     else 
  110.         c->c_classvars = 0;
  111.         
  112.     return c;
  113. }
  114.  
  115. /* construct the IV & CV offset tables */
  116.  
  117. static
  118. buildOffsetTables(c, cl, ivoffset, cvoffset)
  119.     register class        c;
  120.     register classlist    *cl;
  121.     register int        *ivoffset, *cvoffset;
  122. {
  123.     register class        sc;
  124.     
  125.     for (; cl != END; cl = cl->cl_next)
  126.         if ((sc = cl->cl_class) != NULL)        /* ignore bootstrapping Object */
  127.         {
  128.             buildOffsetTables(c, sc->c_superclasses, ivoffset, cvoffset);
  129.             if (c->c_ivoffsets[sc->c_index] == 0) 
  130.                 c->c_ivoffsets[sc->c_index] = *ivoffset;
  131.             if (c->c_cvoffsets != NULL)
  132.                 if (c->c_cvoffsets[sc->c_index] == 0)
  133.                     c->c_cvoffsets[sc->c_index] = *cvoffset;
  134.             *ivoffset += sc->c_lclivsize;
  135.             *cvoffset += sc->c_lclcvsize;
  136.         }
  137. }
  138.  
  139. int
  140. IsA(obj, c)
  141.     register object        obj;
  142.     register class      c;
  143. {
  144.     return (c == *obj);
  145. }
  146.  
  147. int
  148. SubClassOf(c1, c2)
  149.     register class    c1, c2;
  150. {
  151.     register classlist    *cl;
  152.     
  153.     if (c1 == c2)
  154.         return 1;
  155.     for (cl = c1->c_superclasses; cl != END; cl = cl->cl_next)
  156.         if (SubClassOf(cl->cl_class, c2))
  157.             return 1;
  158.     
  159.     return 0;
  160. }
  161.  
  162. int
  163. IsAKindOf(obj, c)
  164.     register object        obj;
  165.     register class      c;
  166. {
  167.     return SubClassOf(ClassOf(obj), c);
  168. }
  169.  
  170. char *
  171. ClassNameOf(obj)
  172.     object    obj;
  173. {
  174.     return    (*obj)->c_name;
  175. }
  176.  
  177. int
  178. IsObj(obj)            /* attempts to tell if this is a valid object */
  179.     object    obj;
  180. {
  181.     return (obj != 0 &&
  182.             ((long)obj & ~0x1L) == (long)obj &&
  183.             ((long)obj & 0xFFFFFF) <= (long)ApplLimit && 
  184.             ClassOf(obj) != 0 && 
  185.             ((long)ClassOf(obj) & ~0x1L) == (long)ClassOf(obj) &&
  186.             ((long)ClassOf(obj) & 0xFFFFFF) <= (long)ApplLimit &&
  187.             ClassOf(obj)->c_classtag == Class);
  188. }
  189.  
  190. InitOIC()
  191. {
  192.     /*
  193.      * Bootstrap the Class system... 
  194.      * Make initial classes and hand patch those bits that assume
  195.      * they already exist.
  196.      */
  197.     
  198.     Object = NULL; classes = NULL; generics = NULL;
  199.     Object = NewClass(0, 0, "Object", END);
  200.     Class = NewClass(sizeof(struct class_struct), 0, "Class", END);
  201.     Class->c_classtag = Class;
  202.     Object->c_classtag = Class;
  203.     free(Object->c_superclasses);
  204.     Object->c_superclasses = END;
  205.     InitObject();
  206.     InitClass();
  207. }
  208.  
  209. /* ------------------------ Method Tables Manager --------------------- */
  210.  
  211. /*
  212.  *         add methods for a given class to generic function method tables.
  213.  *        The class is given followed by a NULL-terminated list of pairs
  214.  *        of methodTable & local function addresses.
  215.  */
  216. AddMethods(c, va_alist)
  217.     class          c;
  218.     va_dcl
  219. {
  220.     va_list                 pvar;
  221.     register GenericTable    *gen;
  222.     
  223.     for (va_start(pvar); (gen = va_arg(pvar, GenericTable *)) != END; )
  224.     {
  225.         AddMethod(c, &gen->gen_mtables[0], (object (*)())va_arg(pvar, char *));
  226.         if (gen->gen_next == UNLINKED)
  227.         {
  228.             gen->gen_next = generics;
  229.             generics = gen;
  230.         }
  231.     }
  232. }
  233.  
  234. /*
  235.  *         add class methods for a given class to generic function method tables.
  236.  */
  237. AddClassMethods(c, va_alist)
  238.     class          c;
  239.     va_dcl
  240. {
  241.     va_list                 pvar;
  242.     register GenericTable    *gen;
  243.     register MethTable        *mth;
  244.     
  245.     for (va_start(pvar); (gen = va_arg(pvar, GenericTable *)) != END; )
  246.     {
  247.         AddMethod(c, &gen->gen_mtables[CLASS], (object (*)())va_arg(pvar, char *));
  248.         if (gen->gen_next == UNLINKED)
  249.         {
  250.             gen->gen_next = generics;
  251.             generics = gen;
  252.         }
  253.     }
  254.  
  255.     c->c_flags |= C_HASCLASSMETHODS;
  256. }
  257.  
  258. /*
  259.  *         add a method for a given class to generic function method tables.
  260.  */
  261. AddMethod(c, mth, func)
  262.     class                  c;
  263.     register MethTable    *mth;
  264.     object                 (*func)();
  265. {
  266.     if (mth->mth_meths == 0)
  267.     {    
  268.         mth->mth_minClass = c->c_index;
  269.         mth->mth_maxClass = c->c_index;
  270.         mth->mth_meths = (Method *)scalloc(sizeof(Method));
  271.     }        
  272.     else if (c->c_index < mth->mth_minClass)
  273.     {
  274.         reallocMethTable(mth, c->c_index - mth->mth_minClass);
  275.         mth->mth_minClass = c->c_index;
  276.     }
  277.     else if (c->c_index > mth->mth_maxClass)
  278.     {
  279.         reallocMethTable(mth, c->c_index - mth->mth_maxClass);
  280.         mth->mth_maxClass = c->c_index;
  281.     }
  282.     
  283.     mth->mth_meths[c->c_index - mth->mth_minClass].mf_func = func;
  284.     mth->mth_meths[c->c_index - mth->mth_minClass].mf_from = c;
  285. }
  286.  
  287. /*
  288.  *        extend a generic function's method function table.
  289.  *        -ve adjustment => add to front, +ve add to end.
  290.  */
  291. static
  292. reallocMethTable(mth, adjustment)
  293.     register MethTable        *mth;
  294.     register int            adjustment;
  295. {
  296.     register int             i, n;
  297.     register Method            *funcs;    
  298.     
  299.     n = mth->mth_maxClass - mth->mth_minClass + 1;
  300.     funcs = (Method *)scalloc(sizeof(Method) * (n + abs(adjustment)));
  301.  
  302.     for (i = 0; i < n; i++)
  303.         funcs[i - ((adjustment < 0) ? adjustment : 0)] = mth->mth_meths[i];
  304.     
  305.     if (mth->mth_meths)
  306.         free(mth->mth_meths);
  307.     mth->mth_meths = funcs;
  308. }
  309.  
  310. char *
  311. GenericName(gen)
  312.     register GenericTable    *gen;
  313. {
  314.     return gen->gen_name;
  315. }
  316.  
  317. /*------------------------ Method Dispatcher -------------------------*/
  318.  
  319. /*  find the method's function
  320.  *
  321.  *    does a breadth-first search of the superclass DAG looking for a
  322.  *    method function. Caches the function in the local class if inherited.
  323.  */
  324. static object
  325. ((*getMethod(c, mth))())
  326.     register class       c;
  327.     register MethTable *mth;
  328. {
  329.     register classlist      *cl;
  330.     register int            i;
  331.     register object            (*func)();
  332.     register Method            *mf, *smf;
  333.  
  334.     /* 
  335.      * check this class
  336.      */
  337.     i = c->c_index - mth->mth_minClass;
  338.     mf = &mth->mth_meths[i];
  339.     if (i >= 0 && c->c_index <= mth->mth_maxClass &&
  340.         (func = mf->mf_func) != NULL)
  341.     {
  342.         currentClass =  mf->mf_from;
  343.         return func;
  344.     }
  345.     
  346.     /*
  347.      *  else, check immediate supers in breadth-first search
  348.      */
  349.     for (cl = c->c_superclasses; cl != END; cl = cl->cl_next)
  350.     {
  351.         i = cl->cl_class->c_index - mth->mth_minClass;
  352.         smf = &mth->mth_meths[i];
  353.         if (i >= 0 && cl->cl_class->c_index <= mth->mth_maxClass &&
  354.             (func = smf->mf_func) != NULL)
  355.         {
  356.             /*
  357.              * inherited, cache it in the local class's method table
  358.              */
  359.             AddMethod(c, mth, func);
  360.             currentClass = 
  361.                 mth->mth_meths[cl->cl_class->c_index - mth->mth_minClass].mf_from;
  362.             mth->mth_meths[c->c_index - mth->mth_minClass].mf_from =
  363.                 currentClass;
  364.             return func;
  365.         }
  366.     }
  367.     
  368.     /*
  369.      *     else, recurse down the superclass DAG
  370.      */
  371.     for (cl = c->c_superclasses; cl != END; cl = cl->cl_next)
  372.         if ((func = getMethod(cl->cl_class, mth)) != NULL)
  373.         {
  374.             AddMethod(c, mth, func);
  375.             mth->mth_meths[c->c_index - mth->mth_minClass].mf_from =
  376.                 currentClass;
  377.             return func;
  378.         }
  379.         
  380.     return NULL;
  381. }
  382.  
  383. /*
  384.  *    dispatch a generic's method function. 
  385.  *  also keeps track of the class in which the current method was found.
  386.  */
  387. object
  388. Dispatch(gen, obj, args)
  389.     register GenericTable    *gen;
  390.     register object            obj;
  391.     char                    *args;
  392. {
  393.     register object    (*func)();
  394.     class              saveCurrentClass;
  395.     GenericTable    *saveCurrentGeneric;
  396.     
  397.     #ifdef IGNORE_NULL_OBJS
  398.         if (obj == NULL)
  399.             return NULL;
  400.     #endif
  401.  
  402.     #ifdef CHECK_OBJS
  403.         if (!IsObj(obj))
  404.         {
  405.             gprintf(error, "** method (%s) to non-object (%lx)\n", gen->gen_name, obj);
  406.             return NULL;
  407.         }
  408.     #endif
  409.     
  410.     saveCurrentClass = currentClass;
  411.     saveCurrentGeneric = currentGeneric;
  412.     if ((func = getMethod(*obj, &gen->gen_mtables[0])) != NULL)
  413.     {
  414.         if (trace)
  415.             traceGeneric(gen, obj);
  416.         gen_level += 1;
  417.         currentGeneric = gen;
  418.  
  419.         obj = (*func)(obj, &((char *)obj)[ClassOf(obj)->c_ivoffsets[currentClass->c_index]], args);
  420.  
  421.         gen_level -= 1;
  422.         currentClass = saveCurrentClass;
  423.         currentGeneric = saveCurrentGeneric;
  424.         
  425.         return obj;
  426.     }
  427.  
  428.     return cantDo(obj, gen, args);
  429. }
  430.  
  431. /*
  432.  *    dispatch a generic's class method function.
  433.  *    
  434.  *    given the class method function table. calls the function with class
  435.  *    and local class variable structure as the 1st 2 args.
  436.  *
  437.  *    if a class method is not found, attempts to invoke the generic as a
  438.  *  normal method on class 'class'.
  439.  *
  440.  *    this function, which could have been integrated with 'Method', is a
  441.  *    separate function in the interests of efficiency.
  442.  */
  443. object
  444. ClassDispatch(gen, c, args)
  445.     register GenericTable    *gen;
  446.     register class          c;
  447.     char                    *args;
  448. {
  449.     register object    (*func)();
  450.     register object    obj;
  451.     class              saveCurrentClass;
  452.     GenericTable    *saveCurrentGeneric;
  453.  
  454.     #ifdef IGNORE_NULL_OBJS
  455.         if (obj == NULL)
  456.             return NULL;
  457.     #endif
  458.  
  459.     #ifdef CHECK_OBJS
  460.         if (!(IsObj(c) && c->c_classtag == Class))
  461.         {
  462.             gprintf(error, "** class method (%s) to non-class (%lx)\n", gen->gen_name, c);
  463.             return  NULL;
  464.         }
  465.     #endif
  466.  
  467.     saveCurrentClass = currentClass;
  468.     saveCurrentGeneric = currentGeneric;
  469.     if ((func = getMethod(c, &gen->gen_mtables[CLASS])) != NULL)
  470.     {
  471.         if (trace)
  472.             traceClassGeneric(gen, c);
  473.         gen_level += 1;
  474.         currentGeneric = gen;
  475.  
  476.         obj = (*func)(c, &(c->c_classvars)[c->c_cvoffsets[currentClass->c_index]], args);
  477.  
  478.         gen_level -= 1;
  479.         currentClass = saveCurrentClass;
  480.         currentGeneric = saveCurrentGeneric;
  481.         
  482.         return obj;
  483.     }
  484.     else
  485.         return Dispatch(gen, c, args);    /* otherwise give it to class Class    */
  486.  
  487. }
  488.  
  489. /*
  490.  *  this function applies the given generic (as its methodtable) to the 
  491.  *    object and arg pointer given.  Often used by "cantDo" to pass on the 
  492.  *    generic to some other object.
  493.  */
  494. object
  495. ApplyGeneric(gen, obj, args)
  496.     GenericTable    *gen;
  497.     register object obj;
  498.     char            *args;
  499. {
  500.     return
  501.         (ClassOf(obj) == Class)    ?
  502.             ClassDispatch(gen, obj, args)
  503.         :
  504.             Dispatch(gen, obj, args);
  505. }
  506.  
  507. int
  508. CanYouDo(obj, gen)    /* can object handle generic ?                    */
  509.     register object        obj;
  510.     register generic    gen;
  511. {
  512.     if (ClassOf(obj) == Class)
  513.         return getMethod(ClassOf(obj), &gen->gen_mtables[CLASS]) != NULL;
  514.     return getMethod(ClassOf(obj), &gen->gen_mtables[0]) != NULL;
  515. }
  516.  
  517. /*  
  518.  *    called by Super to find the method definition next up the superclass
  519.  *    DAG from the current method's class.
  520.  *
  521.  *    does a breadth-first search of the superclass DAG looking for the
  522.  *    method function inherited from the supers further than 'currentClass'.
  523.  *
  524.  *    this function, a slight variant of 'getMethod', is a
  525.  *    separate function in the interests of efficiency.
  526.  */
  527. static object
  528. ((*getSuperMethod(c, mth, beyond))())
  529.     register class       c;
  530.     register MethTable *mth;
  531.     int         beyond;
  532. {
  533.     register classlist      *cl;
  534.     register int            i;
  535.     register object            (*func)();
  536.     register Method            *mf, *smf;
  537.  
  538.     /* 
  539.      * check this class
  540.      */
  541.     i = c->c_index - mth->mth_minClass;
  542.     mf = &mth->mth_meths[i];
  543.     
  544.     if (mf->mf_from == currentClass)
  545.         beyond = 1;
  546.  
  547.     if (beyond &&
  548.         mf->mf_from != currentClass &&     /* ignore current method's class    */
  549.         i >= 0 && c->c_index <= mth->mth_maxClass &&
  550.         (func = mf->mf_func) != NULL)
  551.     {
  552.         currentClass =  mf->mf_from;
  553.         return func;
  554.     }
  555.     
  556.     /*
  557.      *  else, check immediate supers in breadth-first search
  558.      */
  559.     for (cl = c->c_superclasses; cl != END; cl = cl->cl_next)
  560.     {
  561.         i = cl->cl_class->c_index - mth->mth_minClass;
  562.         smf = &mth->mth_meths[i];
  563.         
  564.         if (smf->mf_from == currentClass)
  565.             beyond = 1;
  566.  
  567.         if (beyond &&
  568.             smf->mf_from != currentClass &&
  569.             i >= 0 && cl->cl_class->c_index <= mth->mth_maxClass &&
  570.             (func = smf->mf_func) != NULL)
  571.         {
  572.             currentClass = smf->mf_from;
  573.             return func;
  574.         }
  575.     }
  576.     
  577.     /*
  578.      *     else, recurse down the superclass DAG
  579.      */
  580.     for (cl = c->c_superclasses; cl != END; cl = cl->cl_next)
  581.         if ((func = getSuperMethod(cl->cl_class, mth, beyond)) != NULL)
  582.             return func;
  583.         
  584.     return NULL;
  585. }
  586.  
  587. object
  588. Super(obj, args)
  589.     object                    obj;
  590.     char                    *args;
  591. {
  592.     register object        (*func)();
  593.     class                  saveCurrentClass;
  594.  
  595. #ifdef CHECK_OBJS
  596.     if (!IsObj(obj))
  597.     {
  598.         gprintf(error, "** super method (%s) on non-object (%lx)\n", currentGeneric->gen_name, obj);
  599.         return NULL;
  600.     }
  601. #endif
  602.  
  603.     saveCurrentClass = currentClass;
  604.     if ((func = getSuperMethod(*obj, ¤tGeneric->gen_mtables[0], 0)) != NULL)
  605.     {
  606.         if (trace)
  607.             traceSuperGeneric(currentGeneric, obj);
  608.         gen_level += 1;
  609.  
  610.         obj = (*func)(obj, &((char *)obj)[ClassOf(obj)->c_ivoffsets[currentClass->c_index]], &args);
  611.  
  612.         gen_level -= 1;
  613.         currentClass = saveCurrentClass;
  614.         
  615.         return obj;
  616.     }
  617.     else
  618.         return cantDo(obj, currentGeneric, &args);
  619. }
  620.  
  621. /*
  622.  *    Identical to 'Super', above, except that a pointer to the argument
  623.  *    list is given instead of them being in place.
  624.  *
  625.  *    This allows methods to easily pass their arguments up to the super 
  626.  *    they are invoking (e.g., see 'new' in IndexMixin).
  627.  *
  628.  *    Like other variant functions, it is a separate function in the
  629.  *    interests of efficiency.
  630.  */
  631. object
  632. SuperPassArgs(obj, argp)
  633.     object                    obj;
  634.     char                    **argp;
  635. {
  636.     register object    (*func)();
  637.     class              saveCurrentClass;
  638.  
  639. #ifdef CHECK_OBJS
  640.     if (!IsObj(obj))
  641.     {
  642.         gprintf(error, "** super method (%s) on non-object (%lx)\n", currentGeneric->gen_name, obj);
  643.         return NULL;
  644.     }
  645. #endif
  646.  
  647.     saveCurrentClass = currentClass;
  648.     if ((func = getSuperMethod(*obj, ¤tGeneric->gen_mtables[0], 0)) != NULL)
  649.     {
  650.         if (trace)
  651.             traceSuperGeneric(currentGeneric, obj);
  652.         gen_level += 1;
  653.  
  654.         obj = (*func)(obj, &((char *)obj)[ClassOf(obj)->c_ivoffsets[currentClass->c_index]], argp);
  655.  
  656.         gen_level -= 1;
  657.         currentClass = saveCurrentClass;
  658.         
  659.         return obj;
  660.     }
  661.     else
  662.         return cantDo(obj, currentGeneric, argp);
  663. }
  664.  
  665. /*
  666.  *  invokes super from given inherited class.
  667.  */
  668. object
  669. SuperFrom(c, obj, args)
  670.     class                    c;
  671.     object                    obj;
  672.     char                    *args;
  673. {
  674.     register object        (*func)();
  675.     class                  saveCurrentClass;
  676.  
  677. #ifdef CHECK_OBJS
  678.     if (!IsObj(obj))
  679.     {
  680.         gprintf(error, "** super method (%s) on non-object (%lx)\n", currentGeneric->gen_name, obj);
  681.         return NULL;
  682.     }
  683. #endif
  684.  
  685.     saveCurrentClass = currentClass;
  686.     if ((func = getMethod(c, ¤tGeneric->gen_mtables[0], 0)) != NULL)
  687.     {
  688.         if (trace)
  689.             traceSuperGeneric(currentGeneric, obj);
  690.         gen_level += 1;
  691.  
  692.         obj = (*func)(obj, &((char *)obj)[ClassOf(obj)->c_ivoffsets[currentClass->c_index]], &args);
  693.  
  694.         gen_level -= 1;
  695.         currentClass = saveCurrentClass;
  696.         
  697.         return obj;
  698.     }
  699.     else
  700.         return cantDo(obj, currentGeneric, &args);
  701. }
  702.  
  703. /*---------------------------- Object Maker -----------------------------*/
  704.  
  705. /* 
  706.  *    creates a new instance of the given class. Inits all instance vars to
  707.  *    zero, and sends 'new' to it.
  708.  */ 
  709. object
  710. New(c, args)
  711.     register class       c;
  712.     char                *args;
  713. {
  714.     register object    obj;
  715.     register char    *p;
  716.  
  717.     obj = (object)scalloc(c->c_allocz);
  718.     *obj = c;
  719.     Dispatch(newGeneric, obj, &args);    /* send it the 'new' message    */
  720.     
  721.     return obj;
  722. }
  723.  
  724. int
  725. SizeOf(obj)
  726.     object    obj;
  727. {
  728.     return    ClassOf(obj)->c_allocz;
  729. }
  730.  
  731. static    int    tracing = 0;
  732.  
  733. static
  734. traceGeneric(gen, obj)
  735.     GenericTable    *gen;
  736.     object        obj;
  737. {
  738.     if (!tracing &&
  739.         trace_class == NULL || *obj == trace_class &&
  740.         trace_obj == NULL || obj == trace_obj)
  741.     {
  742.         tracing = 1;
  743.         gprintf(error, "%.*s%s ", gen_level, 
  744.             gen_level ? ".............." : "", GenericName(gen));
  745.         if (ClassOf(obj) != currentClass)
  746.             gprintf(error, "(from %s) ", currentClass->c_name);
  747.         gprintf(error, "on %s @%lx\n", ClassNameOf(obj), obj);
  748.         tracing = 0;
  749.     }
  750. }
  751.  
  752. static
  753. traceClassGeneric(gen, c)
  754.     GenericTable    *gen;
  755.     object        c;
  756. {
  757.     if (!tracing &&
  758.         trace_class == NULL || ClassOf(c) == trace_class &&
  759.         trace_obj == NULL || c == trace_obj)
  760.     {
  761.         tracing = 1;
  762.         gprintf(error, "%.*s%s ", gen_level, 
  763.             gen_level ? ".............." : "", GenericName(gen));
  764.         if ((class)c != currentClass)
  765.             gprintf(error, "(from %s) ", currentClass->c_name);
  766.         gprintf(error, "on class %s @%lx\n", ((class)c)->c_name, c);
  767.         tracing = 0;
  768.     }
  769. }
  770.  
  771. static
  772. traceSuperGeneric(gen, obj)
  773.     GenericTable    *gen;
  774.     object        obj;
  775. {
  776.     if (!tracing &&
  777.         trace_class == NULL || *obj == trace_class &&
  778.         trace_obj == NULL || obj == trace_obj)
  779.     {
  780.         tracing = 1;
  781.         gprintf(error, "%.*ssuper %s ", gen_level, 
  782.             gen_level ? ".........." : "", GenericName(gen));
  783.         if (ClassOf(obj) != currentClass)
  784.             gprintf(error, "(from %s) ", currentClass->c_name);
  785.         gprintf(error, "on %s @%lx\n", ClassNameOf(obj), obj);
  786.         tracing = 0;
  787.     }
  788. }
  789.  
  790. TraceOn()
  791. {
  792.     trace = 1;
  793. }
  794.  
  795. TraceOff()
  796. {
  797.     trace = 0;
  798.     trace_obj = NULL;
  799.     trace_class = NULL;
  800. }
  801.  
  802. TraceObj(obj)
  803.     object    obj;
  804. {
  805.     trace = 1;
  806.     trace_obj = obj;
  807. }
  808.  
  809. TraceClass(c)
  810.     class      c;
  811. {
  812.     trace = 1;
  813.     trace_class = c;
  814. }
  815.  
  816. dumpClass(c)
  817.     register class      c;
  818. {
  819.     register classlist      *cl;
  820.  
  821.     gprintf(error, "Class \"%s\" :\n", c->c_name);
  822.     gprintf(error, "  supers : (");
  823.     for (cl = c->c_superclasses; cl != END; cl = cl->cl_next)
  824.         gprintf(error, "%s%s", cl->cl_class->c_name, (cl->cl_next) ? "," : "");
  825.     gprintf(error, ")\n  index %d\n  cv\'s %lx\n", c->c_index,
  826.         c->c_classvars);
  827. }
  828.  
  829. object
  830. key_arg(arglist, key, default_arg)
  831.     register keyword_args    arglist;
  832.     int                        key;
  833.     object                    default_arg;
  834. {
  835.     for (; *(int *)arglist != key && *(int *)arglist != 0; arglist += sizeof(int) + sizeof(long))
  836.         ;
  837.     if (*(int *)arglist == 0)
  838.         return default_arg;
  839.     else
  840.         return *(object *)(arglist + sizeof(int));
  841. }
  842.